﻿using Acb.Core.Serialize;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using OAuth.Server.Domain;
using OAuth.Server.Domain.Entities;
using OAuth.Server.Domain.Enums;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace OAuth.Server.OAuth.Stores
{
    public class ResourceStore : IResourceStore
    {
        private readonly ResourceRepository _repository;

        public ResourceStore(ResourceRepository repository)
        {
            _repository = repository;
        }

        private static IdentityResource ToIdentity(TResource model)
        {
            var claims = JsonHelper.JsonList<string>(model.Claims ?? "[]");
            return new IdentityResource(model.Name, model.Title, claims)
            {
                Description = model.Description,
                Enabled = model.Enabled,
                Required = model.Required,
                Emphasize = model.Emphasize,
                ShowInDiscoveryDocument = model.ShowInDiscoveryDocument
            };
        }

        private static ApiResource ToApi(TResource model)
        {
            var claims = JsonHelper.JsonList<string>(model.Claims ?? "[]");
            return new ApiResource(model.Name, model.Title, claims)
            {
                Description = model.Description,
                Enabled = model.Enabled
            };
        }

        public async Task<IEnumerable<IdentityResource>> FindIdentityResourcesByScopeAsync(IEnumerable<string> scopeNames)
        {
            var list = new List<IdentityResource>();
            var models = await _repository.QueryByNames(scopeNames, ResourceType.Identity);
            foreach (var model in models)
            {
                var item = ToIdentity(model);
                list.Add(item);
            }

            return list;
        }

        public async Task<IEnumerable<ApiResource>> FindApiResourcesByScopeAsync(IEnumerable<string> scopeNames)
        {
            var list = new List<ApiResource>();
            var models = await _repository.QueryByNames(scopeNames, ResourceType.Api);
            foreach (var model in models)
            {
                var item = ToApi(model);
                list.Add(item);
            }

            return list;
        }

        public async Task<ApiResource> FindApiResourceAsync(string name)
        {
            var model = await _repository.QueryByName(name, ResourceType.Api);
            if (model == null) return null;
            return ToApi(model);
        }

        public async Task<Resources> GetAllResourcesAsync()
        {
            var models = await _repository.QueryAll();
            if (models == null)
                return new Resources();
            var identities = models.Where(t => t.Type == (byte)ResourceType.Identity)
                .Select(ToIdentity);
            var apis = models.Where(t => t.Type == (byte)ResourceType.Api)
                .Select(ToApi);
            return new Resources(identities, apis);
        }
    }
}
